#pragma once

#include <iostream>
#include <vector>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>

using namespace std;

struct TcpServer
{
    struct Desc
    {
        unsigned int port = 1244;
        unsigned int af = AF_INET;
        unsigned int type = SOCK_STREAM;
        unsigned int protocol = IPPROTO_TCP;

        unsigned int sAddr = INADDR_ANY;
        unsigned int sinFamily = AF_INET;

        unsigned int backLog = 10;
    };
    int serv_sock;
    bool Create(const Desc &desc)
    {
        printf("start create");
        serv_sock = socket(desc.af, desc.type, desc.protocol);
        if (serv_sock == -1)
        {
            cout << "server_socket failed" << endl;
            return 0;
        }
        // bind the socket to IP and port
        struct sockaddr_in serv_addr;
        memset(&serv_addr, 0, sizeof(serv_addr)); // use 0 to initialize every byte

        serv_addr.sin_family = desc.af; // use IPV4
        serv_addr.sin_addr.s_addr = htonl(desc.sAddr);
        ;                                      // define IP
        serv_addr.sin_port = htons(desc.port); // define port

        if (bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)))
        {
            cout << "bind failed" << endl;
            return 0;
            return 0;
        }

        // enter listening state, wait for the request from client
        if (listen(serv_sock, desc.backLog) < 0)
        {
            cout << "listen failed" << endl;
            return 0;
        }
        printf("success create the socket\n");
        ;
        return 1;
    }
    void Close()
    {
        close(serv_sock);
    }

    int Accept(struct sockaddr_in &client_addr)
    {
        static socklen_t client_addr_size = sizeof(struct sockaddr_in);

        return accept(serv_sock, (struct sockaddr *)&client_addr, &client_addr_size);
    };
};